/**
 * 1. 执行了 resolve，fulfilled
2. 执行了 reject rejected
3. promise 状态不可逆
4. promise 有 throw reject
5. then 方法 接收两个回调 一个成功 一个失败
    promise fulfilled 成功
    promise rejected 失败
6.  resolve reject 在定时器中执行 定时器结束后执行后续的then
7. then 链式调用
    then 返回一个新的 promise
    返回值是promise对象 返回值成功 新promise就是成功
    返回值是非promise对象 新的promise对象是成功的 值为返回值

8. 执行顺序
 */
class MyPromise {
  constructor(excutor) {
    try {
      this.initBind()
      this.initValue()
      excutor(this.resolve, this.reject)
    } catch (e) {
      this.reject(e)
    }
  }
  initBind() {
    this.resolve = this.resolve.bind(this)
    this.reject = this.reject.bind(this)
  }
  initValue() {
    this.PromiseResult = null
    this.PromiseState = 'pending'
    this.onFilfilledCallbacks = [] // 成功的回调
    this.onRejectedCallbacks = [] // 失败的回调
  }
  resolve(value) {
    if (this.PromiseState !== 'pending') return

    this.PromiseResult = value
    this.PromiseState = 'fulfilled'

    while (this.onFilfilledCallbacks.length > 0) {
      this.onFilfilledCallbacks.shift()(this.PromiseResult)
    }
  }
  reject(reason) {
    if (this.PromiseState !== 'pending') return

    this.PromiseResult = reason
    this.PromiseState = 'rejected'

    while (this.onRejectedCallbacks.length > 0) {
      this.onRejectedCallbacks.shift()(this.PromiseResult)
    }
  }
  then(onFilfilled, onRejected) {
    // console.log('this', this)
    onFilfilled =
      typeof onFilfilled === 'function' ? onFilfilled : (value) => value
    onRejected =
      typeof onRejected === 'function'
        ? onRejected
        : (reason) => {
            throw reason
          }

    var thenPromise = new MyPromise((resolve, reject) => {
      var resolvePromise = (cb) => {
        setTimeout(() => {
          try {
            // 状态
            var result = cb(this.PromiseResult)
            console.log('result', result)

            if (result instanceof MyPromise) {
              // promise对象
              result.then(resolve, reject)
            } else {
              // 非promise对象 成功
              resolve(result)
            }
          } catch (error) {
            reject(error)
          }
        })
      }

      if (this.PromiseState === 'fulfilled') {
        // onFilfilled(this.PromiseResult)
        resolvePromise(onFilfilled)
      } else if (this.PromiseState === 'rejected') {
        // onRejected(this.PromiseResult)
        resolvePromise(onRejected)
      } else if (this.PromiseState === 'pending') {
        this.onFilfilledCallbacks.push(resolvePromise.bind(this, onFilfilled))
        this.onRejectedCallbacks.push(resolvePromise.bind(this, onRejected))
      }
    })

    return thenPromise
  }
  // 接收数组
  //   所有promise都成功 成功结果数组
  //  有一个失败 返回这个失败的结果
  static all(promises) {
    const result = []
    let count = 0

    return new MyPromise((resolve, reject) => {
      const addData = (index, value) => {
        result[index] = value
        count++
        if (count === promises.length) {
          resolve(result)
        }
      }

      promises.forEach((promise, index) => {
        if (promise instanceof MyPromise) {
          promise.then(
            (res) => {
              addData(index, res)
            },
            (err) => reject(err)
          )
        } else {
          addData(index, promise)
        }
      })
    })
  }

  //   哪个promise最快得到结果就返回那个结果 无论成功失败
  static race(promises) {
    return new MyPromise((resolve, reject) => {
      promises.forEach((promise) => {
        if (promise instanceof MyPromise) {
          promise.then(resolve, reject)
        } else {
          resolve(promise)
        }
      })
    })
  }

  //   无论成功失败都 每个结果 集合数组返回
  static allSettled(promises) {
    return new MyPromise((resolve, reject) => {
      const res = []
      let count = 0

      const addData = (status, value, i) => {
        res[i] = { status, value }
        count++
        if (count === promises.length) {
          resolve(res)
        }
      }

      promises.forEach((promise, i) => {
        if (promise instanceof MyPromise) {
          promise.then(
            (value) => addData('fulfilled', value, i),
            (value) => addData('rejected', value, i)
          )
        } else {
          addData('fulfilled', promise, i)
        }
      })
    })
  }

  //   all相反
  //   有一个成功，则返回结果
  static any(promises) {
    return new MyPromise((resolve, reject) => {
      let count = 0
      promises.forEach((promise) => {
        if (promise instanceof MyPromise) {
          promise.then(resolve, () => {
            count++
            if (count === promises.length) {
              reject(new Error('All promises were rejected'))
            }
          })
        } else {
          resolve(promise)
        }
      })
    })
  }
  catch(onRejected) {
    return this.then(undefined, onRejected)
  }
}

// var p1 = new MyPromise((resolve, reject) => {
//   //   resolve('success')
//   //   reject('failed')
//   //   throw 'failed'
//   //   setTimeout(() => reject('failed'), 3000)
//   resolve(1)
// })
//   .then(
//     (res) => res * 10,
//     (res) => console.log('failed', res)
//   )
//   .then(
//     (res) => console.log('success2', res),
//     (res) => console.log('failed2', res)
//   )
// console.log(p1)

var p1 = new MyPromise((resolve, reject) => {
  //   resolve('success')
  //   reject('failed')
  //   throw 'failed'
  //   setTimeout(() => reject('failed'), 3000)
  resolve(1)
})
  .then(
    (res) => new MyPromise((resolve, reject) => reject('failed')),
    (res) => console.log('failed', res)
  )
  .then(
    (res) => console.log('success2', res),
    (res) => console.log('failed2', res)
  )
console.log('done')
